import { unicodeRegExp } from "../utils/tool"

/**模板编译 */

/**vue格式化html正则表达式
 * 正则语法：
 * ?:匹配不捕获
 */
const doctype = /^<!DOCTYPE [^>]+>/i
const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}]*`//匹配命名空间，abc-aaa 
const qnameCapture = `((?:${ncname}\\:)?${ncname})`//匹配自定义标签：<aaa:asdas></aaa:asdas>
const startTagOpen = new RegExp(`^<${qnameCapture}`)//匹配开始标签,返回一个数组，0是"<abc:asd",1是"abc:asd"
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)//匹配结束标签，如:</div>
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;//匹配属性
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g;//匹配{{任意字符}}
const startTagClose = /^\s*(\/?)>/;//匹配标签结束>
// #7298: escape - to avoid being passed as HTML comment when inlined in page
const comment = /^<!\--/
const conditionalComment = /^<!\[/

/**将template模板转换成render函数
 * ast语法树：用树的数据结构来描述原生html，虚拟dom：用对象描述节点 
 **/
export function compileToFunction(template) {
    /**将html转换成ast语法树 */
    let root = parseHTML(template);
    return function render() {

    }
}
/**格式化html字符串
 * 格式化步骤：逐步匹配，将匹配到的字符串删除。
 */
function parseHTML(html) {
    let root;
    while (html) {
        let textEnd = html.indexOf('<');
        /**1.匹配开始标签。textEnd=0，肯定是一个标签，要么开始标签要么结束标签 */
        if (textEnd == 0) {
            let startTagMatch = parseStartTag();//匹配开始标签
            if(startTagMatch){
                continue;//如果匹配到进行下一次匹配
            }
            /**匹配结尾 */
            let endTagMatch=html.match(endTag);
            if(endTagMatch){
                advance(endTagMatch[0].length);//删除匹配到的结束标签
                continue;//进行下次匹配
            }
        }
        let text;
        /**2.匹配文本。即换行后的空白文本*/
        if (textEnd >= 0) {
            text = html.substring(0, textEnd);
            if (text) {
                advance(text.length)
            }
        }
        /**3.匹配结尾 */
    }

    /**格式化开始标签 */
    function parseStartTag() {
        /**1.匹配开始标签 */
        let start = html.match(startTagOpen);//start是一个数组，arguments[0]是<div ，arguments[1]是div

        const match = {
            tagName: [],
            attrs: [],
            type:1,
            parent:null,
            children:[],
        }

        /**如果匹配到开始标签 */
        if (start) {
            advance(start[0].length);//删除开始标签
            match.tagName.push(start[1]);
        }
        /**2.匹配属性 */
        let end, attr;
        /**attr格式是一个数组，arguments数组元素为：
         * 0: " id="app""
         *1: "id"
         *2: "="
         *3: "app"
         *4: undefined
         *5: undefined
         */
        /**当没有匹配到>结束字符，且属性不为空时执行循环 */
        while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
            /**删除属性 */
            advance(attr[0].length);//删除属性
            /**将提取到的属性添加到属性数组 */
            match.attrs.push({ name: attr[1], value: attr[3] || attr[4] || attr[5] });
        }
        //3.匹配闭合字符>，去掉开始标签的>
        if (end) {
            advance(end.length);//去掉闭合字符>
            return match;
        }
    }
    /**advance：前进 */
    function advance(n) {
        html = html.slice(n);
    }
}


/**原生html转ast语法树示例： */
/**
<div id="app">
    <p>hello</p>
</div>

 let root = {
    tag:'div',
    attrs:[
        {name:'id',value:'app'}
    ],
    type:1,
    parent:null,
    children:[
        {
            tag:'p',
            attrs:[],
            type:1,
            parent:root,
            children:[{
                text:'hello',
                type:3
            }]
        }
    ],
}
 */